home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / program / fpk65_66.zip / SOURCE / RTL / DOS / CRT.PP < prev    next >
Text File  |  1996-11-15  |  16KB  |  669 lines

  1. {****************************************************************************
  2.  
  3.                         FPKPascal run time library
  4.                          Copyright (c) 1993,96 by
  5.                      Florian Klaempfl & Michael Spiegel
  6.  
  7.  ****************************************************************************}
  8.  
  9. {
  10.   history:
  11.   29th may 1994: version 1.0
  12.              unit is completed
  13.   14th june 1994: version 1.01
  14.              the address from which startaddr was read wasn't right; fixed
  15.   18th august 1994: version 1.1
  16.              the upper left corner of winmin is now 0,0
  17.   19th september 1994: version 1.11
  18.              keypressed handles extended keycodes false; fixed
  19.   27th february 1995: version 1.12
  20.              * crtinoutfunc didn't the line wrap in the right way;
  21.                fixed
  22.   20th january 1996: version 1.13
  23.              - unused variables removed
  24.   21th august 1996: version 1.14
  25.              * adapted to newer FPKPascal versions
  26.              * make the comments english
  27.    6th november 1996: version 1.49
  28.              * some stuff for DPMI adapted
  29.   15th november 1996: version 1.5
  30.              * bug in screenrows fixed
  31. }
  32.  
  33. unit crt;
  34.  
  35.   interface
  36.   
  37.     uses
  38.        go32;
  39.  
  40.     const
  41.        { screen modes }
  42.        bw40 = 0;
  43.        co40 = 1;
  44.        bw80 = 2;
  45.        co80 = 3;
  46.        mono = 7;
  47.        font8x8 = 256;
  48.  
  49.        { screen color, fore- and background }
  50.        black = 0;
  51.        blue = 1;
  52.        green = 2;
  53.        cyan = 3;
  54.        red = 4;
  55.        magenta = 5;
  56.        brown = 6;
  57.        lightgray = 7;
  58.  
  59.        { only foreground }
  60.        darkgray = 8;
  61.        lightblue = 9;
  62.        lightgreen = 10;
  63.        lightcyan = 11;
  64.        lightred = 12;
  65.        lightmagenta = 13;
  66.        yellow = 14;
  67.        white = 15;
  68.  
  69.        { blink flag }
  70.        blink = $80;
  71.  
  72.     var
  73.        { for compatibility }
  74.        checkbreak,checkeof,checksnow : boolean;
  75.  
  76.        { wenn true, wird von screeensetcursor die Graphikkarte }
  77.        { direkt programmiert                                   }
  78.        directvideo : boolean;
  79.  
  80.        lastmode : word; { screen mode}
  81.        textattr : byte; { current text attribute }
  82.        windmin : word; { Rechte obere Ecke des definierten Fensters }
  83.        windmax : word; { Linke untere Ecke des definierten Fensters }
  84.  
  85.     function keypressed : boolean;
  86.     function readkey : char;
  87.     procedure gotoxy(x,y : byte);
  88.     procedure window(left,top,right,bottom : byte);
  89.     procedure clrscr;
  90.     procedure textcolor(color : byte);
  91.     procedure textbackground(color : byte);
  92.     procedure assigncrt(var f : text);
  93.     function wherex : byte;
  94.     function wherey : byte;
  95.     procedure delline;
  96.     procedure delline(line : byte);
  97.     procedure clreol;
  98.     procedure insline;
  99.     procedure cursoron;
  100.     procedure cursoroff;
  101.     procedure cursorbig;
  102.     procedure lowvideo;
  103.     procedure highvideo;
  104.     procedure nosound;
  105.     procedure sound(hz : word);
  106.     procedure delay(ms : longint);
  107.     procedure textmode(mode : integer);
  108.     procedure normvideo;
  109.     
  110.   implementation
  111.   
  112.     var
  113.        maxcols,maxrows : longint;
  114.   
  115.     type
  116.        pword = ^word;
  117.         
  118.        textbuf = array[0..127] of char;
  119.  
  120.        textrec = record
  121.           handle : word;
  122.           mode : word;
  123.           bufSize : word;
  124.           { private : word; PRIVATE is keyword of FPKPascal }
  125.           _private : word;
  126.           bufpos : word;
  127.           bufend : word;
  128.           bufptr : ^textbuf;
  129.           openfunc : pointer;
  130.           inoutfunc : pointer;
  131.           flushfunc : pointer;
  132.           closefunc : pointer;
  133.           userdata : array[1..16] of byte;
  134.           name : string[79];
  135.           buffer : textbuf;
  136.        end;
  137.        
  138.     { includes low level routines }
  139.  
  140.     {$i modes.inc}
  141.  
  142.     function screenrows : byte;
  143.  
  144.       begin
  145.          dosmemget($40,$84,screenrows,1);
  146.          { don't forget this: }
  147.          inc(screenrows);
  148.       end;
  149.  
  150.     function screencols : byte;
  151.  
  152.       begin
  153.          dosmemget($40,$4a,screencols,1);
  154.       end;
  155.       
  156.     function get_addr(row,col : byte) : word;
  157.     
  158.       begin
  159.          get_addr:=((row-1)*maxcols+(col-1))*2;
  160.       end;
  161.  
  162.     procedure screensetcursor(row,col : longint);
  163.  
  164.       var
  165.          cols : byte;
  166.          pos : word;
  167.  
  168.       begin
  169.          if directvideo then
  170.            begin
  171.               { set new position for the BIOS }
  172.               dosmemput($40,$51,row,1);
  173.               dosmemput($40,$50,col,1);
  174.  
  175.               { calculates screen position }
  176.               dosmemget($40,$4a,cols,1);              
  177.               { FPKPascal calculates with 32 bit }
  178.               pos:=row*cols+col;
  179.  
  180.               { direct access to the graphics card registers }
  181.               outportb($3d4,$0e);
  182.               outportb($3d5,hi(pos)); 
  183.               outportb($3d4,$0f);
  184.               outportb($3d5,lo(pos)); 
  185.            end
  186.          else
  187.             asm
  188.                movb     $0x02,%ah
  189.                movb     $0,%bh
  190.                movb     row,%dh
  191.                movb     col,%dl
  192.                pushl    %ebp
  193.                int      $0x10
  194.                popl     %ebp
  195.             end;
  196.        end;
  197.  
  198.     procedure screengetcursor(var row,col : longint);
  199.  
  200.       begin
  201.          col:=0;
  202.          row:=0;
  203.          dosmemget($40,$50,col,1);
  204.          dosmemget($40,$51,row,1);
  205.       end;
  206.  
  207.     { exported routines }
  208.  
  209.     procedure cursoron;
  210.  
  211.       begin
  212.          asm
  213.             movb   $1,%ah
  214.             movb   $10,%cl
  215.             movb   $9,%ch
  216.             pushl %ebp
  217.             int   $0x10
  218.             popl %ebp
  219.          end;
  220.       end;
  221.    
  222.     procedure cursoroff;
  223.     
  224.       begin
  225.          asm
  226.             movb   $1,%ah
  227.             movb   $-1,%cl
  228.             movb   $-1,%ch
  229.             pushl %ebp
  230.             int   $0x10
  231.             popl %ebp
  232.          end;
  233.       end;
  234.    
  235.     procedure cursorbig;
  236.    
  237.       begin
  238.          asm
  239.             movb   $1,%ah
  240.             movb   $10,%cl
  241.             movb   $1,%ch
  242.             pushl %ebp
  243.             int   $0x10
  244.             popl %ebp
  245.          end;
  246.       end;
  247.       
  248.     var
  249.        is_last : boolean;
  250.        last : char;
  251.  
  252.     function readkey : char;
  253.  
  254.       var
  255.          char2 : char;
  256.          char1 : char;
  257.  
  258.       begin
  259.          if is_last then
  260.            begin
  261.               is_last:=false;
  262.               readkey:=last;
  263.            end
  264.          else
  265.            begin
  266.               asm
  267.                  movb $0,%ah
  268.                  pushl %ebp
  269.                  int $0x16
  270.                  popl %ebp
  271.                  movw %ax,-2(%ebp)
  272.               end;
  273.               if char1=#0 then
  274.                 begin
  275.                    is_last:=true;
  276.                    last:=char2;
  277.                 end;
  278.               readkey:=char1;
  279.            end;
  280.       end;
  281.  
  282.     function keypressed : boolean;
  283.  
  284.       begin
  285.          if is_last then
  286.            begin
  287.               keypressed:=true;
  288.               exit;
  289.            end
  290.          else
  291.            asm
  292.               movb $1,%ah
  293.               pushl %ebp
  294.               int $0x16
  295.               popl %ebp
  296.               setnz %al
  297.               movb %al,__RESULT
  298.            end;
  299.       end;
  300.  
  301.    procedure gotoxy(x,y : byte);
  302.  
  303.      begin
  304.         if (x<1) then
  305.           x:=1;
  306.         if (y<1) then
  307.           y:=1;
  308.         if y+hi(windmin)-2>=hi(windmax) then
  309.           y:=hi(windmax)-hi(windmin)+1;
  310.         if x+lo(windmin)-2>=lo(windmax) then
  311.           x:=lo(windmax)-lo(windmin)+1;
  312.         screensetcursor(y+hi(windmin)-1,x+lo(windmin)-1);
  313.      end;
  314.  
  315.    function wherex : byte;
  316.  
  317.      var
  318.         row,col : longint;
  319.  
  320.      begin
  321.         screengetcursor(row,col);
  322.         wherex:=col-lo(windmin)+1;
  323.      end;
  324.  
  325.    function wherey : byte;
  326.  
  327.      var
  328.         row,col : longint;
  329.  
  330.      begin
  331.         screengetcursor(row,col);
  332.         wherey:=row-hi(windmin)+1;
  333.      end;
  334.  
  335.    procedure window(left,top,right,bottom : byte);
  336.  
  337.      begin
  338.         if (left<1) or
  339.            (right>screencols) or
  340.            (bottom>screenrows) or
  341.            (left>right) or
  342.            (top>bottom) then
  343.            exit;
  344.         windmin:=(left-1) or ((top-1) shl 8);
  345.         windmax:=(right-1) or ((bottom-1) shl 8);
  346.         gotoxy(1,1);
  347.      end;
  348.  
  349.    procedure clrscr;
  350.  
  351.      var
  352.         fil : word;
  353.         row : longint;
  354.  
  355.      begin
  356.         fil:=32 or (textattr shl 8);
  357.         for row:=hi(windmin) to hi(windmax) do
  358.           dosmemfillword($b800,get_addr(row+1,lo(windmin)+1),lo(windmax)-lo(windmin)+1,fil);
  359.         gotoxy(1,1);
  360.      end;
  361.  
  362.    procedure textcolor(color : Byte);
  363.  
  364.      begin
  365.         textattr:=(textattr and $70) or color;
  366.      end;
  367.  
  368.    procedure lowvideo;
  369.  
  370.      begin
  371.         textattr:=textattr and $f7;
  372.      end;
  373.  
  374.    procedure highvideo;
  375.  
  376.      begin
  377.         textattr:=textattr or $08;
  378.      end;
  379.  
  380.    procedure textbackground(color : Byte);
  381.  
  382.      begin
  383.         textattr:=(textattr and $8f) or ((color and $7) shl 4);
  384.      end;
  385.  
  386.    var
  387.       startattrib : byte;
  388.  
  389.    procedure normvideo;
  390.  
  391.      begin
  392.         textattr:=startattrib;
  393.      end;
  394.  
  395.    procedure delline(line : byte);
  396.  
  397.      var
  398.         row,left,right,bot : longint;
  399.         fil : word;
  400.  
  401.      begin
  402.         row:=line+hi(windmin);
  403.         left:=lo(windmin)+1;
  404.         right:=lo(windmax)+1;
  405.         bot:=hi(windmax)+1;
  406.         fil:=32 or (textattr shl 8);
  407.         while (row<bot) do
  408.           begin
  409.              dosmemmove($b800,get_addr(row+1,left),$b800,get_addr(row,left),(right-left+1)*2);
  410.              inc(row);
  411.           end;
  412.         dosmemfillword($b800,get_addr(bot,left),right-left+1,fil);
  413.      end;
  414.  
  415.    procedure delline;
  416.  
  417.      begin
  418.         delline(wherey);
  419.      end;
  420.  
  421.    procedure insline;
  422.  
  423.      var
  424.         row,col,left,right,bot : longint;
  425.         fil : word;
  426.  
  427.      begin
  428.         screengetcursor(row,col);
  429.         inc(row);
  430.         left:=lo(windmin)+1;
  431.         right:=lo(windmax)+1;
  432.         bot:=hi(windmax);
  433.         fil:=32 or (textattr shl 8);
  434.         while (bot>row) do
  435.           begin
  436.              dosmemmove($b800,get_addr(bot-1,left),$b800,get_addr(bot,left),(right-left+1)*2);
  437.              dec(bot);
  438.           end;
  439.         dosmemfillword($b800,get_addr(row,left),right-left+1,fil);
  440.      end;
  441.  
  442.    procedure clreol;
  443.  
  444.      var
  445.         row,col : longint;
  446.         fil : word;
  447.  
  448.      begin
  449.         screengetcursor(row,col);
  450.         inc(row);
  451.         inc(col);
  452.         fil:=32 or (textattr shl 8);
  453.         dosmemfillword($b800,get_addr(row,col),lo(windmax)-col+2,fil);
  454.      end;
  455.  
  456.    procedure crtinoutfunc(var f : textrec);
  457.  
  458.       var
  459.          i,col,row : longint;
  460.          c : char;
  461.          va,sa : word;
  462.  
  463.       begin
  464.          screengetcursor(row,col);
  465.          inc(row);
  466.          inc(col);
  467.          va:=get_addr(row,col);
  468.          if f.mode=fmoutput then
  469.            begin
  470.               for i:=0 to f.bufpos-1 do
  471.                 begin
  472.                    c:=f.buffer[i];
  473.                    case ord(c) of
  474.                       10 : begin
  475.                               inc(row);
  476.                               va:=va+maxcols*2;
  477.                            end;
  478.                       13 : begin
  479.                               col:=lo(windmin)+1;
  480.                               va:=get_addr(row,col);
  481.                           end;
  482.                       8 : if col>lo(windmin)+1 then
  483.                             begin
  484.                                dec(col);
  485.                                va:=va-2;
  486.                             end;
  487.                       7 : begin
  488.                               { beep }
  489.                            end;
  490.                    else
  491.                       begin
  492.                          sa:=textattr shl 8 or ord(c);
  493.                          dosmemput($b800,va,sa,sizeof(sa));
  494.                          inc(col);
  495.                          va:=va+2;
  496.                       end;
  497.                    end;
  498.                    if col>lo(windmax)+1 then
  499.                      begin
  500.                         col:=lo(windmin)+1;
  501.                         inc(row);
  502.  
  503.                         { it's easier to calculate the new address }
  504.                         { it don't spend much time                 }
  505.                         va:=get_addr(row,col);
  506.                      end;
  507.                    while row>hi(windmax)+1 do
  508.                      begin
  509.                         delline(1);
  510.                         dec(row);
  511.                         va:=va-maxcols*2;
  512.                      end;
  513.                 end;
  514.               f.bufpos:=0;
  515.               screensetcursor(row-1,col-1);
  516.            end
  517.          {!!!!!!}
  518.          else halt(100);
  519.       end;
  520.  
  521.    procedure assigncrt(var f : text);
  522.  
  523.      begin
  524.         textrec(f).inoutfunc:=@crtinoutfunc;
  525.         textrec(f).flushfunc:=@crtinoutfunc;
  526.      end;
  527.  
  528.    procedure sound(hz : word);
  529.  
  530.      begin
  531.         if hz=0 then
  532.           begin
  533.              nosound;
  534.              exit;
  535.           end;
  536.         asm
  537.            movzwl hz,%ecx
  538.            movl $1193046,%eax
  539.            cdql
  540.            divl %ecx
  541.            movl %eax,%ecx
  542.            movb $0xb6,%al
  543.            outb %al,$0x43
  544.            movb %cl,%al
  545.            outb %al,$0x42
  546.            movb %ch,%al
  547.            outb %al,$0x42
  548.            inb $0x61,%al
  549.            orb $0x3,%al
  550.            outb %al,$0x61
  551.         end ['EAX','ECX','EDX'];
  552.      end;
  553.  
  554.    procedure nosound;
  555.  
  556.      begin
  557.         asm
  558.            inb $0x61,%al
  559.            andb $0xfc,%al
  560.            outb %al,$0x61
  561.         end ['EAX'];
  562.      end;
  563.  
  564.    var
  565.       calibration : longint;
  566.  
  567.    procedure delay(ms : longint);
  568.  
  569.       var
  570.          i,j : longint;
  571.  
  572.      begin
  573.         for i:=1 to ms do
  574.           for j:=1 to calibration do
  575.              begin
  576.              end;
  577.      end;
  578.  
  579.   function get_ticks : word;
  580.  
  581.     begin
  582.        dosmemget($40,$6c,get_ticks,2);
  583.     end;
  584.  
  585.   procedure initdelay;
  586.  
  587.     var
  588.        first : word;
  589.  
  590.     begin
  591.        calibration:=0;
  592.  
  593.        { wait for new tick }
  594.        first:=get_ticks;
  595.        while get_ticks=first do
  596.          begin
  597.          end;
  598.        first:=get_ticks;
  599.  
  600.        { this estimates calibration }
  601.        while get_ticks=first do
  602.          inc(calibration);
  603.  
  604.        { calculate this to ms }
  605.        calibration:=calibration div 70;
  606.        while true do
  607.          begin
  608.             first:=get_ticks;
  609.             while get_ticks=first do
  610.               begin
  611.               end;
  612.             first:=get_ticks;
  613.             delay(55);
  614.             if first=get_ticks then
  615.                exit
  616.             else begin
  617.                     { decrement calibration two percent }
  618.                     calibration:=calibration-calibration div 50;
  619.                     dec(calibration);
  620.                  end;
  621.          end;
  622.     end;
  623.  
  624.   procedure textmode(mode : integer);
  625.  
  626.     var
  627.        set_font8x8 : boolean;
  628.  
  629.     begin
  630.        lastmode:=mode;
  631.        set_font8x8:=(mode and font8x8)<>0;
  632.        mode:=mode and $ff;
  633.        setscreenmode(mode);
  634.        windmin:=0;
  635.        windmax:=(screencols-1) or ((screenrows-1) shl 8);
  636.        maxcols:=screencols;
  637.        maxrows:=screenrows;
  638.     end;
  639.  
  640. var
  641.    col,row : longint;
  642.  
  643. begin
  644.    is_last:=false;
  645.  
  646.    { direct access to graphics card registers }
  647.    directvideo:=true;
  648.  
  649.    { set output window }
  650.    windmin:=0;
  651.    windmax:=(screencols-1) or ((screenrows-1) shl 8);
  652.  
  653.    { load system variables to temporary variables to save time }
  654.    maxcols:=screencols;
  655.    maxrows:=screenrows;
  656.  
  657.    { save the current settings to restore the old state after the exit }
  658.    screengetcursor(row,col);
  659.    dosmemget($b800,get_addr(row+1,col+1)+1,startattrib,1);
  660.    lastmode:=getscreenmode;
  661.    textattr:=startattrib;
  662.  
  663.    { redirect the standard output }
  664.    assigncrt(output);
  665.  
  666.    { calculates delay calibration }
  667.    initdelay;
  668. end.
  669.